//循环队列
#ifndef __CIRCULARQUEUE__HPP
#define __CIRCULARQUEUE__HPP

#include"VirtualQueue.hpp"

namespace NgSiuKei {

template<class TheClass>
class CircularQueue: public VirtualQueue<TheClass> {
    public:
    CircularQueue(void);
    ~CircularQueue(void);

    public:
    //清空
    void clear(void);
    //获取队头元素
    TheClass getFrontVal(void) const;
    //入队列
    void push(const TheClass val);
    //出队列
    TheClass pop(void);
    //打印队列
    void print(void) const;

    private:
    TheClass *p;
    U_L_L frontIndex;
    U_L_L rearIndex;
};

template<class TheClass>
CircularQueue<TheClass>::CircularQueue(void): VirtualQueue<TheClass>(void) {
    this->p = new TheClass[MAX_SIZE];
    this->frontIndex = 0;
    this->rearIndex = 0;
}

template<class TheClass>
CircularQueue<TheClass>::~CircularQueue(void) {
    delete this->p;
}

template<class TheClass>
void CircularQueue<TheClass>::clear(void) {
    this->size = 0;
    this->frontIndex = 0;
    this->rearIndex = 0;
}

template<class TheClass>
TheClass CircularQueue<TheClass>::getFrontVal(void) const {
    if(this->isEmpty()) {
        throw EXCEPTION_IS_EMPTY;
    }
    return this->p[this->frontIndex];
}

template<class TheClass>
void CircularQueue<TheClass>::push(const TheClass val) {
    if(MAX_SIZE == this->size) {
        throw EXCEPTION_IS_FULL;
    }

    this->p[this->rearIndex] = val;
    this->rearIndex = (this->rearIndex+1)%MAX_SIZE;
    this->size++;
}

template<class TheClass>
TheClass CircularQueue<TheClass>::pop(void) {
    if(this->isEmpty()) {
        throw EXCEPTION_IS_EMPTY;
    }

    TheClass resultVal = this->p[this->frontIndex];
    this->frontIndex = (this->frontIndex+1)%MAX_SIZE;
    this->size--;
    return resultVal;
}

template<class TheClass>
void CircularQueue<TheClass>::print(void) const {
    cout << "打印循环队列：[ ";
    U_L_L currentIndex = this->frontIndex;
    for(U_L_L i=0; i<this->size; i++) {
        cout << this->p[currentIndex] << ' ';
        currentIndex = (currentIndex+1)%MAX_SIZE;
    }
    cout << ']' << endl;
}

}

#endif